package com.grandtech.insurance.common.db.jdbc.sql;

import com.grandtech.insurance.common.db.jdbc.sql.annotation.Column;
import com.grandtech.insurance.common.utils.DateUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by zy on 2017/1/23.
 * 基本类型转换
 */

public final class TransferUtil {
    private TransferUtil() {

    }

    public enum KV {
        //增加
        SAVE {
            @Override
            public Integer getValue() {
                return 2000;
            }

            @Override
            public String toString() {
                return "SAVE";
            }

            @Override
            public String getDesc() {
                return "增加";
            }
        },
        //更新
        UPDATE {
            @Override
            public Integer getValue() {
                return 3000;
            }

            @Override
            public String toString() {
                return "UPDATE";
            }

            @Override
            public String getDesc() {
                return "更新";
            }
        },
        //删除
        DEL {
            @Override
            public Integer getValue() {
                return 4000;
            }

            @Override
            public String toString() {
                return "DEL";
            }

            @Override
            public String getDesc() {
                return "删除";
            }
        },
        //查询
        QUERY {
            @Override
            public Integer getValue() {
                return 5000;
            }

            @Override
            public String toString() {
                return "QUERY";
            }

            @Override
            public String getDesc() {
                return "查询";
            }
        };

        /**
         * @return 对应整数值
         */
        public abstract Integer getValue();

        public abstract String toString();

        public abstract String getDesc();

        /**
         * 根据枚举整型表达式获取枚举对象
         */
        public static KV getEnumByCode(int code) {
            KV state = null;

            for (int i = 0; i < KV.values().length; i++) {
                if (KV.values()[i].getValue() == code) {
                    state = KV.values()[i];
                    break;
                }
            }
            return state;
        }

        /**
         * 根据枚举描名称获取枚举对象
         */
        public static KV getEnumByName(String name) {
            KV state = null;
            for (int i = 0; i < KV.values().length; i++) {
                if (KV.values()[i].toString().equalsIgnoreCase(name.trim())) {
                    state = KV.values()[i];
                    break;
                }
            }
            return state;
        }

        /**
         * 根据枚举描述信息表达式获取枚举对象
         */
        public static KV getEnumByDesc(String desc) {
            KV state = null;
            for (int i = 0; i < KV.values().length; i++) {
                if (KV.values()[i].getDesc().equalsIgnoreCase(desc.trim())) {
                    state = KV.values()[i];
                    break;
                }
            }
            return state;
        }
    }

    /**
     * 根据类型判断
     * key = value 或 key = 'value'
     *
     * @param type
     * @param columnName
     * @param value
     * @return
     */
    public static String objectToKeyEqualValue(Class<?> type, String columnName, Object value) {
        StringBuilder values = new StringBuilder();
        if (type == Integer.class) {
            values.append(columnName);
            values.append(" = ");
            values.append(value);
        } else if (type == Double.class) {
            values.append(columnName);
            values.append(" = ");
            values.append(value);
        } else if (type == Float.class) {
            values.append(columnName);
            values.append(" = ");
            values.append(value);
        } else if (type == Long.class) {
            values.append(columnName);
            values.append(" = ");
            values.append(value);
        } else if (type == Short.class) {
            values.append(columnName);
            values.append(" = ");
            values.append(value);
        } else if (type == String.class) {
            if (value != null) {
                if (value.equals("null")) {
                    values.append(columnName);
                    values.append(" = ");
                    values.append(value);
                } else {
                    values.append(columnName);
                    values.append(" = '");
                    values.append(value);
                    values.append("' ");
                }
            } else {
                values.append(columnName);
                values.append(" = ");
                values.append(value);
            }
        } else if (type == Date.class) {
            values.append(columnName);
            values.append(" = '");
            values.append(value);
            values.append("' ");
        } else {
            values.append(columnName);
            values.append(" = '");
            values.append(value);
            values.append("' ");
        }
        return values.toString();
    }


    /**
     * 根据类型判断
     * key = value 或 key = 'value'
     *
     * @param type
     * @param columnName
     * @param value
     * @return
     */
    public static String objectToKeyEqualValueV1(KV kv, Field field, Class<?> type, String columnName, Object value) {
        StringBuilder values = new StringBuilder();
        /**
         * 获取可能用到的sql方法
         */
        String curFun = "default";
        Column column = field.getAnnotation(Column.class);
        if (kv.getValue().intValue() == KV.UPDATE.getValue().intValue()) {
            curFun = column.update();
        } else if (kv.getValue().intValue() == KV.SAVE.getValue().intValue()) {
            curFun = column.save();
        } else if (kv.getValue().intValue() == KV.QUERY.getValue().intValue()) {
            curFun = column.query();
        } else if (kv.getValue().intValue() == KV.DEL.getValue().intValue()) {
            curFun = column.del();
        }
        if (curFun.equals("default")) {
            if (type == String.class) {
                if (value.equals("null")) {
                    values.append(columnName);
                    values.append(" = ");
                    values.append(value);
                } else {
                    values.append(columnName);
                    values.append(" = '");
                    values.append(value);
                    values.append("' ");
                }
            } else if (type == Date.class) {
                values.append(columnName);
                values.append(" = '");
                values.append(value);
                values.append("' ");
            } else if (type == Timestamp.class) {
                values.append(columnName);
                values.append(" = '");
                values.append(value);
                values.append("' ");
            }else {
                values.append(columnName);
                values.append(" = ");
                values.append(value);
            }
        } else {
            if (type == String.class) {
                if (value.equals("null")) {
                    values.append(columnName);
                    values.append(" = ");
                    value = curFun.replace("?", value.toString());
                    values.append(value);
                } else {
                    values.append(columnName);
                    values.append(" = ");
                    value = curFun.replace("?", value.toString());
                    values.append(value);
                }
            } else if (type == Date.class) {
                values.append(columnName);
                values.append(" = ");
                value = curFun.replace("?", value.toString());
                values.append(value);
            } else {
                values.append(columnName);
                values.append(" = ");
                value = curFun.replace("?", value.toString());
                values.append(value);
            }
        }
        return values.toString();
    }

    /**
     * 可添加特殊函数
     *
     * @param type
     * @param value
     * @return
     */
    public static String objectToSaveValueV1(KV kv, Field field, Class<?> type, Object value) {
        StringBuilder values = new StringBuilder();
        /**
         * 获取可能用到的sql方法
         */
        String curFun = "default";
        Column column = field.getAnnotation(Column.class);
        if (kv.getValue().intValue() == KV.UPDATE.getValue().intValue()) {
            curFun = column.update();
        } else if (kv.getValue().intValue() == KV.SAVE.getValue().intValue()) {
            curFun = column.save();
        } else if (kv.getValue().intValue() == KV.QUERY.getValue().intValue()) {
            curFun = column.query();
        } else if (kv.getValue().intValue() == KV.DEL.getValue().intValue()) {
            curFun = column.del();
        }
        if (curFun.equals("default")) {
            if (type == Integer.class) {
                values.append(value.toString());
                values.append(",");
            } else if (type == Double.class) {
                values.append(value.toString());
                values.append(",");
            } else if (type == Float.class) {
                values.append(value.toString());
                values.append(",");
            } else if (type == Long.class) {
                values.append(value.toString());
                values.append(",");
            } else if (type == Short.class) {
                values.append(value.toString());
                values.append(",");
            } else if (type == String.class) {
                values.append("'");
                values.append(value.toString());
                values.append("',");
            } else if (type == Date.class) {
                values.append("'");
                values.append(value.toString());
                values.append("',");
            } else {
                values.append("'");
                values.append(value.toString());
                values.append("',");
            }
        } else {
            value = curFun.replace("?", value.toString());
            values.append(value.toString());
            values.append(",");
        }
        return values.toString();
    }

    /**
     * @param type
     * @param value
     * @return
     */

    public static String objectToSaveValue(Class<?> type, Object value) {
        StringBuilder values = new StringBuilder();
        if (type == Integer.class) {
            values.append(value.toString());
            values.append(",");
        } else if (type == Double.class) {
            values.append(value.toString());
            values.append(",");
        } else if (type == Float.class) {
            values.append(value.toString());
            values.append(",");
        } else if (type == Long.class) {
            values.append(value.toString());
            values.append(",");
        } else if (type == Short.class) {
            values.append(value.toString());
            values.append(",");
        } else if (type == String.class) {
            values.append("'");
            values.append(value.toString());
            values.append("',");
        } else if (type == Date.class) {
            values.append("'");
            values.append(value.toString());
            values.append("',");
        } else {
            values.append("'");
            values.append(value.toString());
            values.append("',");
        }
        return values.toString();
    }

    public static String objectToInWhere(Class<?> type, Object value) {
        StringBuilder where = new StringBuilder();
        if (type == Integer.class) {
            where.append(value);
            where.append(",");
        } else if (type == Double.class) {
            where.append(value);
            where.append(",");
        } else if (type == Float.class) {
            where.append(value);
            where.append(",");
        } else if (type == Long.class) {
            where.append(value);
            where.append(",");
        } else if (type == Short.class) {
            where.append(value);
            where.append(",");
        } else if (type == String.class) {
            where.append("'");
            where.append(value);
            where.append("',");
        } else if (type == Date.class) {
            where.append("'");
            where.append(value);
            where.append("',");
        } else {
            where.append("'");
            where.append(value);
            where.append("',");
        }
        return where.toString();
    }


    public static Object string2SimpleObject(Field field, String s) {
        Object o = null;
        Type type = field.getType();
        try {
            if (null == s) {
                return null;
            } else if ("".equals(s)) {
                return null;
            } else if (type == Integer.class || type == int.class) {
                o = Integer.parseInt(s);
            } else if (type == Float.class || type == float.class) {
                o = Float.parseFloat(s);
            } else if (type == Double.class || type == double.class) {
                o = Double.parseDouble(s);
            } else if (type == Long.class || type == long.class) {
                o = Long.parseLong(s);
            } else if (type == Short.class || type == short.class) {
                o = Short.parseShort(s);
            } else if (type == String.class) {
                o = s;
            } else if (type == Date.class) {
                o = DateHelper.strToDateTime(s);
            }
        } catch (Exception e) {
            o = null;
            e.printStackTrace();
        }
        return o;
    }


    public static String object2SqlString(Object value) {
        StringBuilder item = new StringBuilder();
        if (value == null) return null;
        Class<?> type = value.getClass();
        if (type == Integer.class) {
            item.append(value);
        } else if (type == Double.class) {
            item.append(value);
        } else if (type == Float.class) {
            item.append(value);
        } else if (type == Long.class) {
            item.append(value);
        } else if (type == Short.class) {
            item.append(value);
        } else if (type == String.class) {
            item.append("'");
            item.append(value);
            item.append("'");
        } else if (type == Date.class) {
            item.append("'");
            item.append(DateUtil.getDAT("yyyy-MM-dd HH:mm:ss", (Date) value));
            item.append("'");
        } else {
            item.append("'");
            item.append(value);
            item.append("'");
        }
        return item.toString();
    }


    public static Object string2SimpleObject(Class type, String s) {
        Object o = null;
        try {
            if (null == s) {
                return null;
            } else if ("".equals(s)) {
                return null;
            } else if (type == Integer.class || type == int.class) {
                o = Integer.parseInt(s);
            } else if (type == Float.class || type == float.class) {
                o = Float.parseFloat(s);
            } else if (type == Double.class || type == double.class) {
                o = Double.parseDouble(s);
            } else if (type == Long.class || type == long.class) {
                o = Long.parseLong(s);
            } else if (type == Short.class || type == short.class) {
                o = Short.parseShort(s);
            } else if (type == String.class) {
                o = s;
            } else if (type == Date.class) {
                o = DateHelper.strToDateTime(s);
            }
        } catch (Exception e) {
            o = null;
            e.printStackTrace();
        }
        return o;
    }


    public static String object2String(Field field, Object obj) {
        String s = null;
        Type type = field.getType();
        try {
            if (null == obj) {
                return "";
            } else if (type == Integer.class || type == int.class) {
                s = ((Integer) obj).toString();
            } else if (type == Float.class || type == float.class) {
                s = ((Float) obj).toString();
            } else if (type == Double.class || type == double.class) {
                s = ((Double) obj).toString();
            } else if (type == Long.class || type == long.class) {
                s = ((Long) obj).toString();
            } else if (type == Short.class || type == short.class) {
                s = ((Short) obj).toString();
            } else if (type == String.class) {
                s = obj.toString();
            } else if (type == Date.class) {
                s = DateHelper.dateTimeToStr((Date) obj);
            }
        } catch (Exception e) {
            s = "";
            e.printStackTrace();
        }
        return s;
    }


    /**
     * 实体转map
     *
     * @param obj
     * @return
     */
    public static Map<String, String> entity2Map(Object obj) {
        Class<? extends Object> clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        Map<String, String> map = new HashMap<>();
        try {
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                String key = field.getName();
                String getMethodName = ReflectUtil.getMethodName(field);
                Method getMethod = clazz.getMethod(getMethodName, new Class[]{});
                Object value = getMethod.invoke(obj, new Object[]{});//获取属性值
                String _value = TransferUtil.object2String(field, value);
                map.put(key, _value);
            }
        } catch (Exception e) {
            e.printStackTrace();
            map = null;
        }
        return map;
    }

    /**
     * 更具实体和指定字段转map
     *
     * @param obj   实体
     * @param array 数据库列名
     * @return
     */
    public static Map<String, Object> T2Map(Object obj, String[] array) {
        Map<String, Object> map = null;
        try {
            map = new HashMap<>();
            Class<? extends Object> clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                Field field = fields[i];
                String columnName = ReflectUtil.getColumnName(field);
                for (int j = 0; j < array.length; j++) {
                    String name = array[j];
                    if (columnName.equals(name)) {
                        String getMethodName = ReflectUtil.getMethodName(field);
                        Method getMethod = clazz.getMethod(getMethodName, new Class[]{});
                        Object value = getMethod.invoke(obj, new Object[]{});//获取属性值
                        map.put(name, value);
                        break;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            map = null;
        }
        return map;
    }

    public static Object map2Entity(Class clazz, Map<String, Object> map) {
        Object obj = null;
        Field[] fields = clazz.getDeclaredFields();
        try {
            obj = clazz.newInstance();
            for (int i = 0; i < fields.length; i++) {
                try {
                    Field field = fields[i];
                    String columnName = ReflectUtil.getColumnName(field);
                    Object objValue = map.get(columnName);
                    objValue = TransferUtil.string2SimpleObject(field, objValue == null ? null : objValue.toString());
                    Method setMethod = ReflectUtil.setMethod(clazz, field);
                    setMethod.invoke(obj, objValue);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }

    public static String map2SimpleWhere(Map<String, Object> condition) {
        StringBuilder where = null;
        if (condition != null && condition.size() > 0) {
            where = new StringBuilder();
            int count = 0;
            int sum = condition.size();
            for (String key : condition.keySet()) {
                count++;
                String k = key;
                Object v = condition.get(k);
                if (v == null) {
                    where.append(k).append(" = null");
                    if (count != sum) {
                        where.append(" and ");
                    }
                } else {
                    if (v instanceof String) {
                        where.append(k).append(" = '").append(v.toString()).append("'");
                    } else {
                        where.append(k).append(" = ").append(v.toString());
                    }

                    if (count != sum) {
                        where.append(" and ");
                    }
                }
            }
            return where.toString();
        }
        return null;
    }
}
